package com.ruyuan.rapid.core.netty.processor.filter.pre;

import com.ruyuan.rapid.common.config.DubboServiceInvoker;
import com.ruyuan.rapid.common.constants.ProcessorFilterConstants;
import com.ruyuan.rapid.common.constants.RapidProtocol;
import com.ruyuan.rapid.core.context.AttributeKey;
import com.ruyuan.rapid.core.context.Context;
import com.ruyuan.rapid.core.context.RapidContext;
import com.ruyuan.rapid.core.context.RapidRequest;
import com.ruyuan.rapid.core.netty.processor.filter.AbstractEntryProcessorFilter;
import com.ruyuan.rapid.core.netty.processor.filter.Filter;
import com.ruyuan.rapid.core.netty.processor.filter.FilterConfig;
import com.ruyuan.rapid.core.netty.processor.filter.ProcessorFilterType;
import lombok.Getter;
import lombok.Setter;

/**
 * 超时的前置过滤器
 * @author mac
 */
@Filter(
        id = ProcessorFilterConstants.TIMEOUT_PRE_FILTER_ID,
        name = ProcessorFilterConstants.TIMEOUT_PRE_FILTER_NAME,
        value = ProcessorFilterType.PRE,
        order = ProcessorFilterConstants.TIMEOUT_PRE_FILTER_ORDER
)
public class TimeoutPreFilter extends AbstractEntryProcessorFilter<TimeoutPreFilter.Config> {

    public TimeoutPreFilter() {
        super(TimeoutPreFilter.Config.class);
    }

    /**
     * 超时过滤器的核心方法实现
     * @param ctx
     * @param args
     * @throws Throwable
     */
    @Override
    public void entry(Context ctx, Object... args) throws Throwable {
        try {
            RapidContext rapidContext = (RapidContext) ctx;
            String protocol = rapidContext.getProtocol();
            Config config = (Config) args[0];
            switch (protocol) {
                case RapidProtocol.HTTP:
                    RapidRequest rapidRequest = rapidContext.getRequest();
                    rapidRequest.setRequestTimeout(config.getTimeout());
                    break;
                case RapidProtocol.DUBBO:
                    DubboServiceInvoker dubboServiceInvoker = (DubboServiceInvoker) rapidContext.getRequiredAttribute(AttributeKey.DUBBO_INVOKER);
                    dubboServiceInvoker.setTimeout(config.getTimeout());
                default:
                    break;
            }
        } finally {
            // 触发下一个过滤器
            super.fireNext(ctx, args);
        }
    }

    @Getter
    @Setter
    public static class Config extends FilterConfig {
        private Integer timeout;
    }
}

